﻿#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.GamerServices;
#endregion

namespace WorkingTitleDungeonCrawler
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class DungeonCrawler : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Player Wizard; // main character of the game
        Map Level;
       // Monster Skeleton; // monster

        List<Projectile> allShots = new List<Projectile>(); // new list for all shots
        Texture2D fireballGfx; //shot graphics

        List<Explosion> allExplosions = new List<Explosion>(); // new list for all explosions
        Texture2D explosionGfx; // explosion graphics

        Texture2D gameoverGfx;

        List<Monster> allSkeletons = new List<Monster>(); // new list for all skeletons
        Texture2D skeletonGfx;

        enum GameState { Start, InGame, GameOver}
        GameState currentGameState = GameState.InGame;


        float timer = 1.5F;
        const float TIMER = 1.5F;
        


       
       //Texture2D DungeonSetGfx;
                

        public DungeonCrawler()
            : base()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here

             Texture2D player = Content.Load<Texture2D>("WizardAll");
           //  Texture2D skeleton = Content.Load<Texture2D>("SkeletonAll");
             skeletonGfx = Content.Load<Texture2D>("SkeletonAll");
             fireballGfx = Content.Load<Texture2D>("Fireball");
             explosionGfx = Content.Load<Texture2D>("explosion");
             Texture2D DungeonSetGfx = Content.Load<Texture2D>("TileSetV1");
             gameoverGfx = Content.Load<Texture2D>("GameOver");


           Wizard = new Player()
           {
               Gfx = player,
               Position = new Vector2(300, 300),
               Direction = new Vector2(0, -1),
               Speed = 0,
               
           };
          Level = new Map(DungeonSetGfx);

          //allSkeletons.Add(new Monster()
          //{
          //    Gfx = skeletonGfx,
          //    Position = new Vector2(50, 50),
          //    Direction = new Vector2(0, -1),
          //    Speed = 1
          //});

          // Skeleton = new Monster() { Gfx = skeleton, Position = new Vector2(100, 100), Direction = new Vector2(0, -1), Speed = 1 };

        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            switch (currentGameState)
            {
                case GameState.InGame:
                    // TODO: Add your update logic here
                    Wizard.Update(gameTime);


                    if (allSkeletons.Count < 10)
                    {
                        allSkeletons.Add(new Monster()
                        {
                            Gfx = skeletonGfx,
                            Position = new Vector2(50, 50),
                            Direction = new Vector2(0, -1),
                            Speed = 1,
                            timer = 1.5F,
                            TIMER = 1.5F
                        });
                    }
                    if (Wizard.ShotFired) // if a shot has been fired
                    {
                        // adds a new shot to the list
                        allShots.Add(new Projectile()
                        {
                            Gfx = fireballGfx,
                            Position = Wizard.Position + (Wizard.Direction * (Wizard.Gfx.Height) / 12) +
                                        (Wizard.Direction * fireballGfx.Height / 12),
                            Angle = Wizard.Angle,
                            Speed = 5.0F + Wizard.Speed,
                            Power = Wizard.ShotPower,
                            Direction = Wizard.Direction
                        });
                        Wizard.ShotPower = 0;
                        Wizard.ShotFired = false;
                    }
                    for (int i = 0; i < allShots.Count; i++)
                    {
                        allShots[i].Update(gameTime);
                        if (allShots[i].Power < 0)
                        {
                            // add an explosion
                            allExplosions.Add(new Explosion() { Gfx = explosionGfx, Position = allShots[i].Position });
                            allShots.RemoveAt(i);
                        }
                    }
                    for (int i = 0; i < allExplosions.Count; i++)
                    {
                        for (int j = 0; j < allSkeletons.Count; j++)
                        {
                            if (allSkeletons[j].CheckCollision(allExplosions[i]))
                            {
                                allSkeletons[j].Life -= 100;
                                
                            }
                        }
                        allExplosions[i].Update(gameTime);
                        if (allExplosions[i].Active == false) allExplosions.RemoveAt(i);
                    }
                    for (int i = 0; i < allSkeletons.Count; i++)
                    {
                        if (Wizard.CheckCollision(allSkeletons[i]))
                        {
                            Wizard.Life -= 1;
                        }
                    }

                    float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
                    timer -= elapsed;

                    for (int i = 0; i < allSkeletons.Count; i++)
                    {
                        allSkeletons[i].timer -= elapsed;

                        if (allSkeletons[i].timer < 1)
                        {


                            allSkeletons[i].Update(gameTime);
                            allSkeletons[i].timer = allSkeletons[i].TIMER; // resets the timer
                        }
                    }

                    // player lose condition
                    if (Wizard.Life < 0)
                    {
                        currentGameState = GameState.GameOver;
                    }
                    for (int i = 0; i < allSkeletons.Count; i++)
                    {
                        if (allSkeletons[i].Life < 0)
                        {
                            allSkeletons.RemoveAt(i);
                        }
                    }
                    base.Update(gameTime);
                    break;

                case GameState.GameOver:
                    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Space))
                    {
                        Exit();
                    }
                    break;

            }
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            // GraphicsDevice.Clear(Color.Black);

            switch (currentGameState)
            {
                case GameState.Start:
                    GraphicsDevice.Clear(Color.Black);
                    spriteBatch.Begin();
                    spriteBatch.End();
                    break;

                case GameState.InGame:
                    GraphicsDevice.Clear(Color.Black);
                    spriteBatch.Begin();

                    // Draws the player and the map
                    Level.Draw(spriteBatch, Wizard.Position);
                    Wizard.Draw(spriteBatch, Wizard.Position);

                    for (int i = 0; i < allSkeletons.Count; i++)
                    {
                        allSkeletons[i].Draw(spriteBatch, Wizard.Position);
                    }
                    //loops through all shots and explosions and draws them on the screen
                    for (int i = 0; i < allShots.Count; i++)
                    {
                        allShots[i].Draw(spriteBatch, Wizard.Position);
                    }
                    for (int i = 0; i < allExplosions.Count; i++)
                    {
                        allExplosions[i].Draw(spriteBatch, Wizard.Position);
                    }
                    spriteBatch.End();
                    break;

                case GameState.GameOver:
                    GraphicsDevice.Clear(Color.Black);
                    spriteBatch.Begin();
                    spriteBatch.Draw(gameoverGfx, new Rectangle(0, 0, Window.ClientBounds.Width, Window.ClientBounds.Height), null, Color.White, 0, Vector2.Zero, SpriteEffects.None, 0);
                    spriteBatch.End();
                    break;
            }
            base.Draw(gameTime);
        }
    }
}
